package com.ning.pummel.cli; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import org.apache.commons.math.stat.descriptive.DescriptiveStatistics; import org.mvel.MVEL; import org.skife.cli.Arguments; import org.skife.cli.Command; import org.skife.cli.Option; import com.ning.pummel.Fight; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStreamReader; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; @Command(name = "step") public class Step implements Callable<Void> { @Option(name = {"-m", "--max"}, title = "max-requests", description = "Maximum number of requests to execute") public int maxRequests = -1; @Option(name = {"-s", "--start"}, description = "initial concurrency level, defaults to 100") public int start = 1; @Option(name = "--step", title = "step-function", description = "clojure function to apply to generate next step, default is 'c + 1'") public String stepFunction = "c + 1"; @Option(name = {"-l", "--labels"}, description = "Show column labels") public boolean labels = false; @Option(name = {"-L", "--limit"}, description = "concurrency limit to stop at, default is " + Integer.MAX_VALUE) public int limit = Integer.MAX_VALUE; @Option(name = {"-p", "--percentile"}, description = "Percentile to try to target, default is 99th percentile") public double percentile = 99.0; @Arguments(title = "url file", description = "input file to pull urls from, otherwise will use stdin") public File urlFile; public Void call() throws Exception { List<String> urls = Lists.newArrayList(); final BufferedReader in; if (urlFile != null) { in = new BufferedReader(new InputStreamReader(new FileInputStream(urlFile))); } else { in = new BufferedReader(new InputStreamReader(System.in)); } for (String line = in.readLine(); line != null; line = in.readLine()) { if (maxRequests >= 0) { if (maxRequests == 0) { break; } else if (maxRequests > 0) { maxRequests--; } } urls.add(line); } if (labels) {System.out.printf("clients\ttp%.1f\tmean\treqs/sec\n", percentile);} int concurrency = start; do { DescriptiveStatistics stats = new Fight(concurrency, urls).call(); System.out.printf("%d\t%.2f\t%.2f\t%.2f\n", concurrency, stats.getPercentile(percentile), stats.getMean(), (1000 / stats.getMean()) * concurrency); Map<String, Integer> vals = ImmutableMap.of("c", concurrency); concurrency = (Integer) MVEL.eval(stepFunction, vals); } while (concurrency < limit); return null; } }